package vasys.mehaniksspacemars;


import com.mojang.serialization.Lifecycle;
import net.minecraft.core.Holder;
import net.minecraft.core.IRegistry;
import net.minecraft.core.IRegistryWritable;
import net.minecraft.core.RegistryMaterials;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.MinecraftKey;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.WorldServer;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.world.level.biome.BiomeBase;
import net.minecraft.world.level.biome.BiomeFog;
import net.minecraft.world.level.biome.BiomeSettingsGeneration;
import net.minecraft.world.level.biome.BiomeSettingsMobs;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.chunk.ChunkGenerator;
import org.bukkit.Bukkit;
import org.bukkit.block.Biome;
import org.bukkit.craftbukkit.v1_20_R2.CraftServer;
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R2.block.CraftBiome;
import org.bukkit.craftbukkit.v1_20_R2.block.CraftBlock;
import org.bukkit.event.EventHandler;
import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.generator.BiomeProvider;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class CustomBiomes {


    public static IRegistry<BiomeBase> getBiomeRegistry()
    {
        //ap is BIOME
        //aU is registryAccess
        //d is registryOrThrow
        return MinecraftServer.getServer().aU().d(Registries.ap);
    }

    @SuppressWarnings("deprecation")
    static public void regBiomes() {
        CraftServer craftserver = (CraftServer)Bukkit.getServer();
        DedicatedServer dedicatedserver = craftserver.getServer();
        MinecraftServer minecraftServer = MinecraftServer.getServer();
        //ResourceKey<BiomeBase> oldKey = ResourceKey.a(Registries.ap, new MinecraftKey("minecraft", "forest"));
        IRegistryWritable<BiomeBase> registrywritable = (IRegistryWritable<BiomeBase>) getBiomeRegistry();
        //BiomeBase forestbiome = registrywritable.a(oldKey);
        BiomeBase forestbiome = CraftBiome.bukkitToMinecraft(Biome.FOREST);
        BiomeBase basalt_deltas = CraftBiome.bukkitToMinecraft(Biome.BASALT_DELTAS);
        BiomeBase soul_sand = CraftBiome.bukkitToMinecraft(Biome.SOUL_SAND_VALLEY);

        try {
            Field frozen = RegistryMaterials.class.getDeclaredField("l");
            frozen.setAccessible(true);
            frozen.set(registrywritable, false);
            MehaniksSpaceMars.getPlugin(MehaniksSpaceMars.class).getLogger().info("Unfreezing biome registry");
        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e1) {
            e1.printStackTrace();
        }

        try {
            regBiomeBase(registrywritable, dedicatedserver, soul_sand, "mars_vales", true, "d0a37c", "2389da", "1ca3ec", "a0b0b8", "6db33f", "6db33f");
            regBiomeBase(registrywritable, dedicatedserver, basalt_deltas, "mars_caves", false, "51493a", "2389da", "1ca3ec", "a97850", "6db33f", "6db33f");
            MehaniksSpaceMars.getPlugin(MehaniksSpaceMars.class).getLogger().info("Registered custom biomes: mars_vales, mars_caves");
        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException |
                 InvocationTargetException | NoSuchMethodException e) {
            MehaniksSpaceMars.getPlugin(MehaniksSpaceMars.class).getLogger().info("Failed to register custom biomes: mars_vales, mars_caves");
            e.printStackTrace();
        }

        try {
            Field frozen = RegistryMaterials.class.getDeclaredField("l");
            frozen.setAccessible(true);
            frozen.set(registrywritable, true);
            MehaniksSpaceMars.getPlugin(MehaniksSpaceMars.class).getLogger().info("Freezing biome registry");
        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e1) {
            e1.printStackTrace();
        }
    }

    private static void regBiomeBase(IRegistryWritable<BiomeBase> registrywritable, DedicatedServer dedicatedserver, BiomeBase defbiome, String newKeyName, Boolean cold, String fogColor, String waterColor, String waterFogColor, String skyColor, String foliageColor, String grassColor) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        ResourceKey<BiomeBase> newKey = ResourceKey.a(Registries.ap, new MinecraftKey("mehaniks", newKeyName));

        BiomeBase.a newBiomeBuilder = new BiomeBase.a();

        //BiomeBase.b is ClimateSettings
        //d is temperatureModifier
        //This temperature modifier stuff is more cleanly handled below.
//		Class<?> climateSettingsClass = Class.forName("net.minecraft.world.level.biome.BiomeBase.b");
//		Field temperatureModififierField = climateSettingsClass.getDeclaredField("d");
//		temperatureModififierField.setAccessible(true);

        //i is climateSettings
        //Field f = BiomeBase.class.getDeclaredField("i");
        //f.setAccessible(true);
        //newBiomeBuilder.a((BiomeBase.TemperatureModifier) temperatureModififierField.get(f.get(forestbiome)));
        newBiomeBuilder.a(defbiome.c()); //c is getPrecipitation

        //k is mobSettings
        Field biomeSettingMobsField = BiomeBase.class.getDeclaredField("k");
        biomeSettingMobsField.setAccessible(true);
        BiomeSettingsMobs biomeSettingMobs = (BiomeSettingsMobs) biomeSettingMobsField.get(defbiome);
        newBiomeBuilder.a(biomeSettingMobs);

        //j is generationSettings
        Field biomeSettingGenField = BiomeBase.class.getDeclaredField("j");
        biomeSettingGenField.setAccessible(true);
        BiomeSettingsGeneration biomeSettingGen = (BiomeSettingsGeneration) biomeSettingGenField.get(defbiome);
        newBiomeBuilder.a(biomeSettingGen);

        //newBiome.a(0.2F); //Depth of biome (Obsolete?)
        //newBiome.b(0.05F); //Scale of biome (Obsolete?)
        newBiomeBuilder.a(0.7F); //Temperature of biome
        newBiomeBuilder.b(0.05F); //Downfall of biome

        //BiomeBase.TemperatureModifier.a will make your biome normal
        //BiomeBase.TemperatureModifier.b will make your biome frozen
        if(cold)
            newBiomeBuilder.a(BiomeBase.TemperatureModifier.b);
        else
            newBiomeBuilder.a(BiomeBase.TemperatureModifier.a);

        BiomeFog.a newFog = new BiomeFog.a();
        //newFog.a(BiomeFog.GrassColor.a); //This doesn't affect the actual final grass color, just leave this line as it is or you will get errors

        //Set biome colours. If field is empty, default to forest color

        //fogcolor
        newFog.a(Integer.parseInt(fogColor,16));

        //water color i is getWaterColor
        newFog.b(Integer.parseInt(waterColor,16));

        //water fog color j is getWaterFogColor
        newFog.c(Integer.parseInt(waterFogColor,16));

        //sky color
        newFog.d(Integer.parseInt(skyColor,16));

        //Unnecessary values; can be removed safely if you don't want to change them

        //foliage color (leaves, fines and more) f is getFoliageColor
        newFog.e(Integer.parseInt(foliageColor,16));

        //grass blocks color
        newFog.f(Integer.parseInt(grassColor,16));

        newBiomeBuilder.a(newFog.a());

        BiomeBase biome = newBiomeBuilder.a(); //biomebuilder.build();

        //Inject into the data registry for biomes
        //RegistryGeneration.a(RegistryGeneration.i, newKey, biome);

        //c is containsKey
        if(registrywritable.c(newKey)) {
            MehaniksSpaceMars.getPlugin(MehaniksSpaceMars.class).getLogger().info(newKey + " was already registered.");
            return;
        }
        Holder.c<BiomeBase> holder = registrywritable.a(newKey, biome, Lifecycle.stable());
        Method bindValue = Holder.c.class.getDeclaredMethod("b", Object.class);
        bindValue.setAccessible(true);
        bindValue.invoke(holder, biome);


    }


}
